package hotnet.listener;

import hotnet.exception.ExceptionMonitor;
import hotnet.filter.IoFilterChain;
import hotnet.service.IoService;
import hotnet.session.IoSession;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

public class IoServiceListenerManager {
	private final AtomicBoolean activated = new AtomicBoolean(); 
	private final IoService service;
	private final List<IoServiceListener> listeners = new CopyOnWriteArrayList<IoServiceListener>();
	
	public IoServiceListenerManager(IoService service) {
		this.service = service;
	}
	
	public void addListener(IoServiceListener listener) {
		listeners.add(listener);
	}
	
	public void remove(IoServiceListener listener) {
		if (listener == null) 
			return;
		
		listeners.remove(listener);
	}
	
	public int getManagedSessionCount() {
		return listeners.size();
	}
	
	public void fireServiceActivated() {
		if (!activated.compareAndSet(false, true)) {
			return;
		}
		for (IoServiceListener listener : listeners) {
			try {
				listener.serviceActivated(service);
			} catch (Exception e) {
				ExceptionMonitor.getInstance().exceptionCaught(e);
			}
		}
	}
	
	public void fireServiceDeactivated() {
		for (IoServiceListener listener : listeners) {
			try {
				listener.serviceActivated(service);
			} catch (Exception e) {
				ExceptionMonitor.getInstance().exceptionCaught(e);
			}
		}
	}
	
	public void fireSessionCreate(IoSession session) {
		IoFilterChain filterChain = session.getFilterChain();
		filterChain.fireSessionCreated();
		filterChain.fireSessionOpened();
		
		for (IoServiceListener listener : listeners) {
			try {
				listener.sessionCreate(session);
			} catch (Exception e) {
				ExceptionMonitor.getInstance().exceptionCaught(e);
			}
		}
	}
	
	public void fireSessionClosed(IoSession session) {
		for (IoServiceListener listener : listeners) {
			try {
				listener.sessionClosed(session);
			} catch (Exception e) {
				ExceptionMonitor.getInstance().exceptionCaught(e);
			}
		}
	}
	
	public void fireSessionDestroyed(IoSession session) {
		session.getFilterChain().fireSessionClosed();
		
		for (IoServiceListener listener : listeners) {
			try {
				listener.sessionDestroyed(session);
			} catch (Exception e) {
				ExceptionMonitor.getInstance().exceptionCaught(e);
			}
		}
	}
	
    public boolean isActive() {
        return activated.get();
    }
}
